package com.ke.forum.socket.handler;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.corundumstudio.socketio.AckRequest;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.annotation.OnConnect;
import com.corundumstudio.socketio.annotation.OnDisconnect;
import com.corundumstudio.socketio.annotation.OnEvent;
import com.ke.forum.mbg.dao.ChatSessionMapper;
import com.ke.forum.mbg.entity.ChatHistory;
import com.ke.forum.mbg.entity.ChatSession;
import com.ke.forum.mbg.entity.dto.ChatSessionDto;
import com.ke.forum.mbg.entity.dto.UserDto;
import com.ke.forum.shiro.config.shiro.JWTToken;
import com.ke.forum.socket.config.Event;
import com.ke.forum.socket.service.ChatHistoryService;
import com.ke.forum.socket.service.ChatSessionService;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.Optional;
import java.util.UUID;

@Component
@Slf4j
public class MessageHandler {

    @Autowired
    DefaultSecurityManager defaultSecurityManager;
    @Autowired
    RedisTemplate<String,Object> redisTemplate;
    @Autowired
    ChatSessionService chatSessionService;
    @Autowired
    ChatHistoryService chatHistoryService;
    @Autowired
    ChatSessionMapper chatSessionMapper;

    final String CONNECT_KEY = "forum-user:";

    @OnConnect
    public void onConnect(SocketIOClient client){
        if (client!=null){
            UserDto userDto = getUserInfoFromClient(client);
            String uuid = userDto.getUuid();
            UUID sessionId = client.getSessionId();
            assert uuid !=null;
            redisTemplate.opsForValue().set(CONNECT_KEY+uuid,sessionId);
            log.info("连接成功,【uuid】= {},【sessionId】= {}", uuid, sessionId);

        }
    }

    @OnDisconnect
    public void OnDisconnect(SocketIOClient client){
        if(client!=null){
            UserDto userDto = getUserInfoFromClient(client);
            String uuid = userDto.getUuid();
            UUID sessionId = client.getSessionId();
            assert uuid !=null;
            redisTemplate.delete(CONNECT_KEY+uuid);
            log.info("客户端断开连接，【uuid】={}，【sessionId】={}",uuid,sessionId);
        }
    }

    /**
     * check消息
     */
    @OnEvent(value = Event.CHECK)
    public void onCheckEvent(SocketIOClient client, AckRequest request, ChatSession chatSession){
        UserDto userDto = getUserInfoFromClient(client);
        chatSession.setNeedCheck(0);
        chatSessionService.updateById(chatSession);
        client.sendEvent(Event.EMAIL,chatSessionService.listChatSessionByUserUuid(userDto.getUuid()));
    }

    @OnEvent(value = Event.CHAT)
    public void onChatEvent(SocketIOClient client,AckRequest request,ChatHistory data){
        log.info(data.toString());
        Optional<UUID> toUser = Optional.empty();
        String sessionId = (String) redisTemplate.opsForValue().get(CONNECT_KEY+data.getToUuid());
        if (sessionId!=null){
            toUser = Optional.of(UUID.fromString(sessionId));
        }
        ChatSession mySession = chatSessionMapper.selectOne(Wrappers.<ChatSession>lambdaQuery().eq(ChatSession::getFromUuid, data.getFromUuid()).eq(ChatSession::getFromUuid, data.getToUuid()));
        ChatSession toSession = chatSessionMapper.selectOne(Wrappers.<ChatSession>lambdaQuery().eq(ChatSession::getFromUuid, data.getToUuid()).eq(ChatSession::getFromUuid, data.getFromUuid()));
        if (mySession==null){
            UUID uuid = UUID.randomUUID();
            String chatSessionId = uuid.toString();
            mySession = ChatSession.builder().fromUuid(data.getFromUuid()).toUuid(data.getToUuid())
                    .lastMessage(data.getMessage()).lastTime(LocalDateTime.now()).sessionId(sessionId).needCheck(0).build();
            toSession = ChatSession.builder().fromUuid(data.getToUuid()).toUuid(data.getFromUuid())
                    .lastMessage(data.getMessage()).lastTime(LocalDateTime.now()).sessionId(sessionId).needCheck(1).build();
            if (data.getType().equals(1)) {
                toSession.setLastMessage("图片");
                mySession.setLastMessage("图片");
            } else if (data.getType().equals(2)) {
                toSession.setLastMessage("语音");
                mySession.setLastMessage("语音");
            }
            chatSessionMapper.insert(mySession);
            chatSessionMapper.insert(toSession);
            data.setSessionId(chatSessionId);
        }else {
            mySession.setLastTime(LocalDateTime.now());
            toSession.setLastTime(LocalDateTime.now());
            if (data.getType().equals(1)) {
                toSession.setLastMessage("图片");
                mySession.setLastMessage("图片");
            } else if (data.getType().equals(2)) {
                toSession.setLastMessage("语音");
                mySession.setLastMessage("语音");
            }else {
                toSession.setLastMessage(data.getMessage());
                mySession.setLastMessage(data.getMessage());
            }
            toSession.setNeedCheck(toSession.getNeedCheck()+1);
            chatSessionMapper.updateById(mySession);
            chatSessionMapper.updateById(toSession);
        }
        chatHistoryService.save(data);
        //用户在线
    }

    public UserDto getUserInfoFromClient(SocketIOClient client){
        String token = client.getHandshakeData().getSingleUrlParam("token");
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        Subject subject = SecurityUtils.getSubject();
        subject.login(new JWTToken(token));
        return (UserDto) subject.getPrincipal();
    }

    //发送到信箱
    public void sendToEmail(){

    }
}
